home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!rutgers!gatech!bloom-beacon!husc6!m2c!necntc!ncoast!allbery
- From: jfh@rpp386.UUCP (The Beach Bum)
- Newsgroups: comp.sources.misc
- Subject: v03i090: fuser for 386 xenix (+ repost of Unix PC version)
- Message-ID: <8807130006.AA13998@rpp386.UUCP>
- Date: 13 Jul 88 05:06:38 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: jfh@rpp386.UUCP (The Beach Bum)
- Lines: 1008
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 3, Issue 90
- Submitted-by: "The Beach Bum" <jfh@rpp386.UUCP>
- Archive-name: xenix-fuser
-
- brando -
-
- ha! rich $alz last hacked on this before me so far as i can tell. this
- probably belongs to him (for posting) but working on 386 xenix only seems
- as .misc as it gets.
-
- the next major submission will be a reimplementation of crash which runs
- on, you guessed it, 386 xenix only! i'm not into writing portable code
- this week.
-
- - john.
- --
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # README
- # fuser.1
- # Makefile
- # fuser.c.sco
- # fuser.c.u-pc
- # This archive created: Sun Jul 3 11:21:31 1988
- # By: The Beach Bum (Big "D" Home for Wayward Hackers)
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'README'
- then
- echo shar: "will not over-write existing file 'README'"
- else
- sed 's/^X//' << \SHAR_EOF > 'README'
- X[ This has been ported to SCO Xenix for the Intel 80386. There are
- X two versions of the program. The differences were large than the
- X entire sharchive, so I saw no point in including context diffs.
- X The Makefile should explain everything. Ideally, the machine
- X dependencies would be separated into different files. - john. ]
- X
- X[ This program takes a filename, searches the kernel's open file
- X table, and determines who has that file open. You can to kill the
- X offending process(es). This is useful for backups, e.g. A port of
- X this to BSD and other Unices would be nice. --r$ ]
- X
- XHere is the latest source to my version of the fuser(1M) command, written
- Xand running on the Unix PC. A man page and makefile are included.
- X
- XVerify that the macros in "Makefile" are correct for you (LBIN, for example
- Xshould be where you want the program to be installed), and run make AS ROOT.
- XIt is important to do the make as root so that the resulting program will
- Xhave the set-uid bit set, allowing it to read the kernel's memory.
- X
- X
- XSome notes to anyone who wants to port this program to something other
- Xthan the Unix PC:
- X
- XThe Unix PC has "tunable kernel parameters", which mean that things that
- Xare constants on most older Unix systems are variable. This version of
- Xfuser reads the values of these variables from the kernel's memory. I have
- Xtried to make most of this transparent, for ease of porting to a more plain-
- Xvanilla Unix. For example, I have 'int' varialbes called 'NOFILE', 'NPROC',
- Xetc., which emulate the #defines present in 'standard' Unix. To make it
- Xrun on such systems, it should be possible to remove these variables and
- Xthe code that sets them, and the program will use the #defines from
- X<sys/*.h>. The only other significant change is that because NOFILE is
- Xvariable, the u_ofile field in the user structure is a pointer rather than
- Xan array. This means that you can delete the code that copies the u_ofile
- Xlist since it is already right in the user structure.
- X
- X
- X -=] Ford [=-
- X
- X"GNU does not eliminate (In Real Life: Michael Ditto)
- Xall the world's problems, kenobi!ford@crash.CTS.COM
- Xonly some of them." -rms ...!crash!kenobi!ford
- X
- X
- XHere's the shar file:
- SHAR_EOF
- fi
- if test -f 'fuser.1'
- then
- echo shar: "will not over-write existing file 'fuser.1'"
- else
- sed 's/^X//' << \SHAR_EOF > 'fuser.1'
- X.TH FUSER 1M
- X.SH NAME
- Xfuser \- find processes using a file or filesystem
- X.SH SYNOPSIS
- X.B fuser
- X[-ku] files [...]
- X.SH DESCRIPTION
- X.I Fuser
- Xsearches the kernel's internal tables to find all processes that are
- Xaccessing the listed
- X.I files.
- XIf one of the
- X.I files
- Xis a block special file (such as a disk) then fuser finds processes that
- Xare accessing any file on that device.
- X.P
- X.I Fuser
- Xlists on its standard output the process ID of each process found
- Xto be using any of the files
- Xspecified. The process IDs will be followed by the letters
- X.B c,
- X.B r,
- Xor
- X.B p,
- Xif the file is open as the current directory, root directory, or
- Xparent directory of the process, respectively. (The kernel has a process'
- Xparent directory "open" for internal use under certain conditions.)
- X.SH OPTIONS
- XThe -k option causes
- X.I fuser
- Xto attempt to kill each process found with the SIGKILL signal (normal
- Xpermission controls apply; see kill(2)).
- X.P
- XThe -u option causes
- X.I fuser
- Xto print, in parentheses, the user ID of the owner of each process listed.
- X.P
- XOptions may be re-specified between filenames; a '-' argument by itself
- Xturns off the -k and -u options.
- X.P
- XThe process IDs are written to standard output, one line per file searched
- Xfor. Other output is written to standard error.
- X.SH EXAMPLES
- Xfuser /tmp/foo
- X.br
- X.RS
- XThis prints the process IDs of all processes that have the file /tmp/foo open.
- X.RE
- X.P
- Xfuser -u /dev/fp021
- X.br
- X.RS
- XThis finds all processes that are accessing any file on the disk /dev/fp021.
- XThe process IDs and user names of the process owners are listed.
- XThis is useful to find out why a disk can not be unmounted.
- X.RE
- X.P
- Xfuser -k /dev/fp021
- X.br
- Xumount /dev/fp021
- X.br
- X.RS
- XIf run by super-user, this kills all processes that are preventing
- Xthe disk /dev/fp021 from being unmounted, and then unmounts the disk.
- X.RE
- X.SH BUGS
- XIf a process's user area is swapped (happens on some versions of UNIX)
- Xfuser will print a warning and ignore that process.
- SHAR_EOF
- fi
- if test -f 'Makefile'
- then
- echo shar: "will not over-write existing file 'Makefile'"
- else
- sed 's/^X//' << \SHAR_EOF > 'Makefile'
- XSHELL=/bin/sh
- XLBIN=/usr/local/bin
- XINSTALL=cp
- X
- X# Set this to version of .c file you want. fuser.c.sco is for SCO Xenix
- X# for a 386. fuser.c.u-pc is for Unix System V on an Unix PC.
- XFUSER=fuser.c.sco
- X# FUSER=fuser.c.u-pc
- X
- X# Set this to group which owns /dev/swap, /dev/mem and /dev/kmem. Those
- X# files MUST be readable by that group. Otherwise, the program must be
- X# SUID root to be used by anyone other than root, or other special
- X# arrangements must be made, all of which could compromise the system.
- X# ADMIN=root
- XADMIN=sysinfo
- X
- X# Debugging flags
- X# CFLAGS=-DDEBUG -g
- X# LDFLAGS=-g
- X
- X# Production flags
- XCFLAGS=-O
- XLDFLAGS=-s
- X
- Xfuser: fuser.o
- X $(CC) $(LDFLAGS) -o fuser fuser.o
- X
- Xinstall: fuser
- X $(INSTALL) fuser $(LBIN)
- X chown root $(LBIN)/fuser
- X chgrp $(ADMIN) $(LBIN)/fuser
- X chmod 2711 $(LBIN)/fuser
- X
- Xclean:
- X -rm -f *.o core
- X
- Xclobber: clean
- X -rm -f fuser.c fuser $(LBIN)/fuser
- X
- Xfuser.c: $(FUSER)
- X cp $(FUSER) fuser.c
- SHAR_EOF
- fi
- if test -f 'fuser.c.sco'
- then
- echo shar: "will not over-write existing file 'fuser.c.sco'"
- else
- sed 's/^X//' << \SHAR_EOF > 'fuser.c.sco'
- X/************************************************************
- X *
- X * This program was written by me, Mike "Ford" Ditto, and
- X * I hereby release it into the public domain in the interest
- X * of promoting the development of free, quality software
- X * for the hackers and users of the world.
- X *
- X * Feel free to use, copy, modify, improve, and redistribute
- X * this program, but keep in mind the spirit of this
- X * contribution; always provide source, and always allow
- X * free redistribution (shareware is fine with me). If
- X * you use a significant part of this code in a program of
- X * yours, I would appreciate being given the appropriate
- X * amount of credit.
- X * -=] Ford [=-
- X *
- X ************************************************************/
- X
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <ctype.h>
- X#include <pwd.h>
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <sys/sysmacros.h>
- X#include <sys/stat.h>
- X#include <sys/inode.h>
- X#include <sys/file.h>
- X#include <sys/seg.h>
- X#include <sys/page.h>
- X#include <sys/text.h>
- X#include <sys/proc.h>
- X#include <sys/signal.h>
- X#include <sys/dir.h>
- X#include <sys/user.h>
- X#include <sys/var.h>
- X
- Xextern char *sbrk();
- Xextern long lseek();
- Xextern void perror(), exit();
- Xextern struct passwd *getpwuid();
- Xextern char *malloc();
- X
- X
- Xchar *progname;
- X
- X#define inodeaddr (mysyms[0].xl_value)
- X#define fileaddr (mysyms[1].xl_value)
- X#define procaddr (mysyms[2].xl_value)
- X#define varaddr (mysyms[3].xl_value)
- X
- Xstruct xlist mysyms[] =
- X{
- X { 0,0,0,"_inode" },
- X { 0,0,0,"_file" },
- X { 0,0,0,"_proc" },
- X { 0,0,0,"_v" },
- X { 0,0,0,(char *)0 }
- X};
- X
- Xchar buf[BUFSIZ];
- X
- Xint kmem, mem, swap, kflag, uflag;
- Xint NINODE, NFILE, NPROC;
- X
- Xstruct inode *inodep;
- Xstruct file *filep;
- Xstruct proc *procp;
- Xstruct var *var;
- X
- X
- X/* main program for fuser(1M), a program which lists */
- X/* processes that are using the given file(s) */
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int status=0;
- X
- X progname = *argv;
- X
- X setup();
- X
- X while (++argv,--argc)
- X if ((*argv)[0]=='-')
- X {
- X register char c, *i;
- X
- X kflag=uflag=0;
- X
- X i = *argv+1;
- X while (c= *i++) switch(c)
- X {
- X case 'k':
- X ++kflag;
- X break;
- X case 'u':
- X ++uflag;
- X break;
- X default:
- X fprintf(stderr, "%s: bad flag `-%c'\n", progname, c);
- X fprintf(stderr,
- X "Usage: %s [-ku] files [[-] [-ku] files]\n",
- X progname);
- X return -1;
- X }
- X }
- X else {
- X printf ("%s: ", *argv);
- X status += fuser(*argv);
- X putchar ('\n');
- X }
- X return status;
- X}
- X
- X
- X/* a fast, zeroizing, memory allocator for things */
- X/* that will never need to be freed */
- Xchar *myalloc(nbytes)
- Xlong nbytes;
- X{
- X register char *ptr;
- X
- X ptr = malloc((unsigned) nbytes);
- X if (! ptr)
- X {
- X sprintf(buf, "%s: no memory!", progname);
- X perror(buf);
- X exit(1);
- X }
- X memset (ptr, 0, nbytes);
- X
- X return ptr;
- X}
- X
- X
- X/* one-time setup of main data structures from the kernel */
- Xsetup()
- X{
- X if ( (kmem=open("/dev/kmem", O_RDONLY)) < 0 )
- X {
- X sprintf(buf, "%s: can't open /dev/kmem", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X if ( (mem=open("/dev/mem", O_RDONLY)) < 0 )
- X {
- X sprintf(buf, "%s: can't open /dev/mem", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X if ( (swap=open("/dev/swap", O_RDONLY)) < 0 )
- X {
- X sprintf(buf, "%s: can't open /dev/swap", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X if (xlist("/xenix", mysyms))
- X {
- X sprintf(buf, "%s: can't xlist /xenix", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X setuid(getuid());
- X
- X#ifdef DEBUG
- X fprintf(stderr, "inode: 0x%08lx\n", inodeaddr);
- X fprintf(stderr, "file: 0x%08lx\n", fileaddr);
- X fprintf(stderr, "proc: 0x%08lx\n", procaddr);
- X fprintf(stderr, "var: 0x%08lx\n", varaddr);
- X#endif DEBUG
- X
- X var = (struct var *)myalloc((long) sizeof (struct var));
- X kcopy((char *)var, varaddr, (long) sizeof (struct var));
- X
- X NINODE = var->v_inode;
- X NFILE = var->v_file;
- X NPROC = var->v_proc;
- X
- X#ifdef DEBUG
- X fprintf(stderr, "NOFILE: %d\n", NOFILE);
- X fprintf(stderr, "NINODE: %d\n", NINODE);
- X fprintf(stderr, "NFILE: %d\n", NFILE);
- X fprintf(stderr, "NPROC: %d\n", NPROC);
- X#endif DEBUG
- X
- X inodep = (struct inode *)myalloc((long) sizeof (struct inode) * NINODE);
- X filep = (struct file *)myalloc((long) sizeof (struct file) * NFILE);
- X procp = (struct proc *)myalloc((long) sizeof (struct proc) * NPROC);
- X
- X kcopy((char *)inodep, inodeaddr, (long) sizeof (struct inode) * NINODE);
- X kcopy((char *)filep, fileaddr, (long) sizeof (struct file) * NFILE);
- X kcopy((char *)procp, procaddr, (long) sizeof (struct proc) * NPROC);
- X}
- X
- X
- X/* copy bytes from physical address space to this process */
- Xpcopy(caddr, paddr, nbytes)
- Xchar *caddr;
- Xlong paddr;
- Xlong nbytes;
- X{
- X if ( lseek(mem, paddr, 0)<0L ||
- X read(mem, caddr, (unsigned)nbytes) != nbytes )
- X {
- X sprintf(buf, "%s: can't read /dev/mem", progname);
- X perror(buf);
- X exit(1);
- X }
- X}
- X
- X
- X/* copy bytes from kernel address space to this process */
- Xkcopy(caddr, kaddr, nbytes)
- Xchar *caddr;
- Xlong kaddr;
- Xlong nbytes;
- X{
- X if ( lseek(kmem, kaddr, 0)<0L ||
- X read(kmem, caddr, (unsigned)nbytes) != nbytes )
- X {
- X sprintf(buf, "%s: can't read /dev/kmem", progname);
- X perror(buf);
- X exit(1);
- X }
- X}
- X
- Xfindu (proc, slot, user)
- Xstruct proc *proc;
- Xint slot;
- Xstruct user *user;
- X{
- X long swapaddr;
- X int i;
- X
- X if ((proc->p_flag & (SSWAP|SSPART)) || ! (proc->p_flag & SLOAD)) {
- X swapaddr = proc->p_addr[0].te_frameno * NBPC;
- X lseek (swap, swapaddr, 0);
- X if (read (swap, user, sizeof *user) < 0)
- X return (0);
- X } else {
- X lseek (mem, proc->p_addr[0].te_frameno * NBPC, 0);
- X if (read (mem, user, sizeof *user) < 0)
- X return (0);
- X }
- X if ((user->u_procp - (struct proc *) procaddr) == slot)
- X return (1);
- X else
- X return (0);
- X}
- X/* Return a pointer to a local copy of the user structure */
- X/* for process number `procidx'. Returns NULL if procidx */
- X/* refers to an invalid (not-in-use or otherwise) slot. */
- Xstruct user *getuser(procidx)
- Xint procidx;
- X{
- X static struct user **users;
- X struct file **ofile;
- X long upage;
- X
- X#ifdef DEBUG
- X fprintf (stderr, "Looking for upage for proc %d\n", procidx);
- X#endif
- X if (!procp[procidx].p_stat ||
- X procp[procidx].p_stat == SIDL ||
- X procp[procidx].p_stat == SZOMB)
- X return 0;
- X
- X if (!users)
- X users = (struct user **)myalloc((long) sizeof (struct user *) * NPROC);
- X
- X if (!users[procidx])
- X {
- X /* allocate and copy in the user structure */
- X users[procidx] = (struct user *)myalloc((long) sizeof (struct user));
- X if (! findu (&procp[procidx], procidx, users[procidx]))
- X return 0;
- X }
- X return users[procidx];
- X}
- X
- X
- X/* find all users of the file `name' */
- Xfuser(name)
- Xchar *name;
- X{
- X register i;
- X int filesys;
- X struct stat Stat;
- X
- X if (stat(name, &Stat))
- X {
- X sprintf(buf, "%s: can't stat %s", progname, name);
- X perror(buf);
- X return 1;
- X }
- X
- X /* see if we are looking for a whole filesystem */
- X filesys = ((Stat.st_mode & S_IFMT) == S_IFBLK);
- X
- X#ifdef DEBUG
- X if (filesys)
- X fprintf(stderr, "looking for files on dev=%d,%d\n",
- X bmajor(Stat.st_rdev), minor(Stat.st_rdev));
- X else
- X fprintf(stderr, "looking for dev=%d,%d, ino=%d\n",
- X bmajor(Stat.st_dev), minor(Stat.st_dev), Stat.st_ino);
- X#endif DEBUG
- X
- X for ( i=0 ; i<NINODE ; ++i )
- X {
- X if ( inodep[i].i_count &&
- X ((filesys && (inodep[i].i_dev == Stat.st_rdev))
- X || (inodep[i].i_dev == Stat.st_dev &&
- X inodep[i].i_number == Stat.st_ino)) )
- X {
- X#ifdef DEBUG
- X fprintf(stderr, "Found it! inodep[%d], i_size is %ld\n",
- X i, inodep[i].i_size);
- X#endif DEBUG
- X
- X iuser((struct inode *)inodeaddr + i);
- X }
- X }
- X
- X return 0;
- X}
- X
- X
- X#define CHECK(kaddr, type) if (kaddr==kinode) { if (++flag==1) printf(" %d", procp[i].p_pid); if (type) putchar(type); }
- X
- X/* find all users of the inode at kernel address `kinode' */
- Xiuser(kinode)
- Xstruct inode *kinode;
- X{
- X register int i, j;
- X int flag;
- X struct user *user;
- X struct passwd *pwd;
- X struct text text;
- X
- X#ifdef DEBUG
- X fprintf(stderr, "Looking for users of inode at kernel address 0x%08lx\n",
- X kinode);
- X#endif DEBUG
- X
- X for ( i=0 ; i<NPROC ; ++i )
- X if (user = getuser(i))
- X {
- X#ifdef DEBUG
- X fprintf(stderr, "%03d: pid=%5d addr[0]=%05x addr[1]=%05x\n",
- X i, procp[i].p_pid, procp[i].p_addr[0], procp[i].p_addr[1]);
- X#endif DEBUG
- X
- X#ifdef DEBUG
- X fprintf(stderr, " user = 0x%08lx\n", user);
- X#endif DEBUG
- X
- X fflush(stderr);
- X flag=0;
- X if (procp[i].p_textp) {
- X kcopy((char *)&text, procp[i].p_textp, (long) sizeof (struct text));
- X CHECK(text.x_iptr, 't');
- X }
- X
- X CHECK(user->u_cdir, 'c');
- X CHECK(user->u_rdir, 'r');
- X CHECK(user->u_pdir, 'p');
- X
- X for ( j=0 ; !flag && j<NOFILE ; ++j )
- X if (user->u_ofile[j])
- X CHECK(filep[user->u_ofile[j]-(struct file *)fileaddr].f_inode, 0);
- X fflush(stdout);
- X
- X if (flag)
- X {
- X if (uflag)
- X {
- X if ( (pwd=getpwuid((int)procp[i].p_uid)) )
- X fprintf(stderr, "(%s)", pwd->pw_name);
- X else
- X fprintf(stderr, "(%d)", procp[i].p_uid);
- X }
- X if (kflag && procp[i].p_pid)
- X if (kill(procp[i].p_pid, SIGKILL))
- X {
- X sprintf(buf, "%s: can't kill process %d",
- X progname, procp[i].p_pid);
- X perror(buf);
- X }
- X }
- X }
- X}
- SHAR_EOF
- fi
- if test -f 'fuser.c.u-pc'
- then
- echo shar: "will not over-write existing file 'fuser.c.u-pc'"
- else
- sed 's/^X//' << \SHAR_EOF > 'fuser.c.u-pc'
- X/************************************************************
- X *
- X * This program was written by me, Mike "Ford" Ditto, and
- X * I hereby release it into the public domain in the interest
- X * of promoting the development of free, quality software
- X * for the hackers and users of the world.
- X *
- X * Feel free to use, copy, modify, improve, and redistribute
- X * this program, but keep in mind the spirit of this
- X * contribution; always provide source, and always allow
- X * free redistribution (shareware is fine with me). If
- X * you use a significant part of this code in a program of
- X * yours, I would appreciate being given the appropriate
- X * amount of credit.
- X * -=] Ford [=-
- X *
- X ************************************************************/
- X
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <ctype.h>
- X#include <pwd.h>
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <sys/sysmacros.h>
- X#include <sys/stat.h>
- X#include <sys/tune.h>
- X#include <sys/inode.h>
- X#include <sys/file.h>
- X#include <sys/user.h>
- X#include <sys/proc.h>
- X#include <sys/signal.h>
- X#include <a.out.h>
- X
- X/* get rid of meaningless NOFILE from param.h */
- X#ifdef NOFILE
- X#undef NOFILE
- X#endif
- X
- Xextern char *sbrk();
- Xextern long lseek();
- Xextern void perror(), exit();
- Xextern struct passwd *getpwuid();
- X
- X
- Xchar *progname;
- X
- X#define tuhiaddr (mysyms[0].n_value)
- X#define inodeaddr (mysyms[1].n_value)
- X#define fileaddr (mysyms[2].n_value)
- X#define procaddr (mysyms[3].n_value)
- X#define nofileaddr (mysyms[4].n_value)
- X
- Xstruct nlist mysyms[] =
- X{
- X { "tuhi", },
- X { "inode", },
- X { "file", },
- X { "proc", },
- X { "nofile", },
- X { (char *)0, },
- X};
- X
- Xchar buf[BUFSIZ];
- X
- Xint kmem, mem, kflag, uflag;
- Xint NINODE, NFILE, NPROC, NOFILE;
- X
- Xstruct inode *inode;
- Xstruct file *file;
- Xstruct proc *proc;
- X
- X
- X/* main program for fuser(1M), a program which lists */
- X/* processes that are using the given file(s) */
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int status=0;
- X
- X progname = *argv;
- X
- X setup();
- X
- X while (++argv,--argc)
- X if ((*argv)[0]=='-')
- X {
- X register char c, *i;
- X
- X kflag=uflag=0;
- X
- X i = *argv+1;
- X while (c= *i++) switch(c)
- X {
- X case 'k':
- X ++kflag;
- X break;
- X case 'u':
- X ++uflag;
- X break;
- X default:
- X fprintf(stderr, "%s: bad flag `-%c'\n", progname, c);
- X fprintf(stderr,
- X "Usage: %s [-ku] files [[-] [-ku] files]\n",
- X progname);
- X return -1;
- X }
- X }
- X else
- X status += fuser(*argv);
- X
- X return status;
- X}
- X
- X
- X/* a fast, zeroizing, memory allocator for things */
- X/* that will never need to be freed */
- Xchar *myalloc(nbytes)
- Xlong nbytes;
- X{
- X register char *ptr = sbrk((int)nbytes);
- X
- X if ((long)ptr < 0L)
- X {
- X sprintf(buf, "%s: no memory!", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X return ptr;
- X}
- X
- X
- X/* one-time setup of main data structures from the kernel */
- Xsetup()
- X{
- X struct tunable tune;
- X
- X if ( (kmem=open("/dev/kmem", O_RDONLY)) < 0 )
- X {
- X sprintf(buf, "%s: can't open /dev/kmem", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X if ( (mem=open("/dev/mem", O_RDONLY)) < 0 )
- X {
- X sprintf(buf, "%s: can't open /dev/mem", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X if (nlist("/unix", mysyms))
- X {
- X sprintf(buf, "%s: can't nlist /unix", progname);
- X perror(buf);
- X exit(1);
- X }
- X
- X setuid(getuid());
- X
- X kcopy((char *)&NOFILE, nofileaddr, (long) sizeof NOFILE);
- X
- X#ifdef DEBUG
- X fprintf(stderr, "tuhi: 0x%08lx\n", tuhiaddr);
- X#endif DEBUG
- X kcopy((char *)&tune, tuhiaddr, (long) sizeof tune);
- X
- X /* do indirection on these addresses, since they */
- X /* are just pointers in the kernel */
- X kcopy((char *)&inodeaddr, inodeaddr, (long) sizeof inodeaddr);
- X kcopy((char *)&fileaddr, fileaddr, (long) sizeof fileaddr);
- X kcopy((char *)&procaddr, procaddr, (long) sizeof procaddr);
- X
- X#ifdef DEBUG
- X fprintf(stderr, "inode: 0x%08lx\n", inodeaddr);
- X fprintf(stderr, "file: 0x%08lx\n", fileaddr);
- X fprintf(stderr, "proc: 0x%08lx\n", procaddr);
- X#endif DEBUG
- X
- X NINODE = tune.ninode;
- X NFILE = tune.nfile;
- X NPROC = tune.nproc;
- X
- X#ifdef DEBUG
- X fprintf(stderr, "NOFILE: %d\n", NOFILE);
- X fprintf(stderr, "NINODE: %d\n", NINODE);
- X fprintf(stderr, "NFILE: %d\n", NFILE);
- X fprintf(stderr, "NPROC: %d\n", NPROC);
- X#endif DEBUG
- X
- X inode = (struct inode *)myalloc((long) sizeof (struct inode) * NINODE);
- X file = (struct file *)myalloc((long) sizeof (struct file) * NFILE);
- X proc = (struct proc *)myalloc((long) sizeof (struct proc) * NPROC);
- X
- X kcopy((char *)inode, inodeaddr, (long) sizeof (struct inode) * NINODE);
- X kcopy((char *)file, fileaddr, (long) sizeof (struct file) * NFILE);
- X kcopy((char *)proc, procaddr, (long) sizeof (struct proc) * NPROC);
- X}
- X
- X
- X/* copy bytes from physical address space to this process */
- Xpcopy(caddr, paddr, nbytes)
- Xchar *caddr;
- Xlong paddr;
- Xlong nbytes;
- X{
- X if ( lseek(mem, paddr, 0)<0L ||
- X read(mem, caddr, (unsigned)nbytes) != nbytes )
- X {
- X sprintf(buf, "%s: can't read /dev/mem", progname);
- X perror(buf);
- X exit(1);
- X }
- X}
- X
- X
- X/* copy bytes from kernel address space to this process */
- Xkcopy(caddr, kaddr, nbytes)
- Xchar *caddr;
- Xlong kaddr;
- Xlong nbytes;
- X{
- X if ( lseek(kmem, kaddr, 0)<0L ||
- X read(kmem, caddr, (unsigned)nbytes) != nbytes )
- X {
- X sprintf(buf, "%s: can't read /dev/kmem", progname);
- X perror(buf);
- X exit(1);
- X }
- X}
- X
- X
- X/* Return a pointer to a local copy of the user structure */
- X/* for process number `procidx'. Returns NULL if procidx */
- X/* refers to an invalid (not-in-use or otherwise) slot. */
- Xstruct user *getuser(procidx)
- Xint procidx;
- X{
- X static struct user **users;
- X struct file **ofile;
- X long upage;
- X
- X if (!proc[procidx].p_stat ||
- X proc[procidx].p_stat == SIDL ||
- X proc[procidx].p_stat == SZOMB)
- X return 0;
- X
- X if (!(proc[procidx].p_flag & SLOAD))
- X {
- X /* can't handle swapped process yet */
- X fprintf(stderr, "%s: can't handle swapped process %d (flag=%05x)\n",
- X progname, proc[procidx].p_pid, proc[procidx].p_flag);
- X return 0;
- X }
- X
- X if (!users)
- X users = (struct user **)myalloc((long) sizeof (struct user *) * NPROC);
- X
- X if (!users[procidx])
- X {
- X upage = (long)ctob(proc[procidx].p_addr[0]);
- X
- X /* allocate and copy in the user structure */
- X users[procidx] = (struct user *)myalloc((long) sizeof (struct user));
- X pcopy((char *)(users[procidx]),
- X upage + U_OFFSET,
- X (long) sizeof (struct user));
- X
- X /* allocate and copy in the list of file pointers */
- X ofile = (struct file **)myalloc((long) sizeof (struct file *) * NOFILE);
- X pcopy((char *)ofile,
- X upage+(long)(users[procidx]->u_ofile)-VPG_BASE,
- X (long) sizeof (struct file *) * NOFILE);
- X users[procidx]->u_ofile = ofile;
- X }
- X
- X return users[procidx];
- X}
- X
- X
- X/* find all users of the file `name' */
- Xfuser(name)
- Xchar *name;
- X{
- X register i;
- X int filesys;
- X struct stat Stat;
- X
- X if (stat(name, &Stat))
- X {
- X sprintf(buf, "%s: can't stat %s", progname, name);
- X perror(buf);
- X return 1;
- X }
- X
- X /* see if we are looking for a whole filesystem */
- X filesys = ((Stat.st_mode&S_IFMT) == S_IFBLK);
- X
- X#ifdef DEBUG
- X if (filesys)
- X fprintf(stderr, "looking for files on dev=%d,%d\n",
- X bmajor(Stat.st_rdev), minor(Stat.st_rdev));
- X else
- X fprintf(stderr, "looking for dev=%d,%d, ino=%d\n",
- X bmajor(Stat.st_dev), minor(Stat.st_dev), Stat.st_ino);
- X#endif DEBUG
- X
- X for ( i=0 ; i<NINODE ; ++i )
- X {
- X if ( inode[i].i_count &&
- X (filesys
- X ? (brdev(inode[i].i_dev) == Stat.st_rdev)
- X : (brdev(inode[i].i_dev) == Stat.st_dev &&
- X inode[i].i_number == Stat.st_ino)) )
- X {
- X#ifdef DEBUG
- X fprintf(stderr, "Found it! inode[%d], i_size is %ld\n",
- X i, inode[i].i_size);
- X#endif DEBUG
- X
- X iuser((struct inode *)inodeaddr + i);
- X }
- X }
- X
- X putchar('\n');
- X
- X return 0;
- X}
- X
- X
- X#define CHECK(kaddr, type) if (kaddr==kinode) { if (++flag==1) printf(" %d", proc[i].p_pid); if (type) putchar(type); }
- X
- X/* find all users of the inode at kernel address `kinode' */
- Xiuser(kinode)
- Xstruct inode *kinode;
- X{
- X register int i, j;
- X int flag;
- X struct user *user;
- X struct passwd *pwd;
- X
- X#ifdef DEBUG
- X fprintf(stderr, "Looking for users of inode at kernel address 0x%08lx\n",
- X kinode);
- X#endif DEBUG
- X
- X for ( i=0 ; i<NPROC ; ++i )
- X if (user = getuser(i))
- X {
- X#ifdef DEBUG
- X fprintf(stderr, "%03d: pid=%5d addr[0]=%05x addr[1]=%05x swaddr=%05x\n",
- X i, proc[i].p_pid, proc[i].p_addr[0], proc[i].p_addr[1],
- X proc[i].p_swaddr);
- X#endif DEBUG
- X
- X#ifdef DEBUG
- X fprintf(stderr, " user = 0x%08lx\n", user);
- X fprintf(stderr, " user->u_ofile = 0x%08lx\n", user->u_ofile);
- X#endif DEBUG
- X
- X fflush(stderr);
- X flag=0;
- X CHECK(user->u_cdir, 'c');
- X CHECK(user->u_rdir, 'r');
- X CHECK(user->u_pdir, 'p');
- X for ( j=0 ; !flag && j<NOFILE ; ++j )
- X if (user->u_ofile[j])
- X CHECK(file[user->u_ofile[j]-(struct file *)fileaddr].f_inode, 0);
- X fflush(stdout);
- X
- X if (flag)
- X {
- X if (uflag)
- X {
- X if ( (pwd=getpwuid((int)proc[i].p_uid)) )
- X fprintf(stderr, "(%s)", pwd->pw_name);
- X else
- X fprintf(stderr, "(%d)", proc[i].p_uid);
- X }
- X if (kflag && proc[i].p_pid)
- X if (kill(proc[i].p_pid, SIGKILL))
- X {
- X sprintf(buf, "%s: can't kill process %d",
- X progname, proc[i].p_pid);
- X perror(buf);
- X }
- X }
- X }
- X}
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-